package com.webyweather.android;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.util.Log;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.webyweather.android.adapter.WeByWeatherFragmentStatePagerAdapter;
import com.webyweather.android.constant.Constants;

import java.io.IOException;
import java.sql.Timestamp;

public class WeByWeatherActivity extends SherlockFragmentActivity {

    private static final String TAG = "com.webyweather.android.WeByWeatherActivity";

    private String mRegId;

    private ViewPager mViewPager;

    private FragmentStatePagerAdapter mPagerAdapter;

    private GoogleCloudMessaging mGcm;


    private Context mContext;

    private final ActionBar.TabListener tabListener = new ActionBar.TabListener() {

        @Override
        public void onTabSelected (final ActionBar.Tab tab, final FragmentTransaction ft) {
            WeByWeatherActivity.this.mViewPager.setCurrentItem(tab.getPosition(), true);
        }

        @Override
        public void onTabUnselected (final ActionBar.Tab tab, final FragmentTransaction ft) {
        }

        @Override
        public void onTabReselected (final ActionBar.Tab tab, final FragmentTransaction ft) {
        }
    };

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate (final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        this.mContext = getApplicationContext();
        this.mRegId = getRegistrationId(this.mContext);
        if (mRegId.length() == 0) {
            registerBackground();
        }

        this.mGcm = GoogleCloudMessaging.getInstance(this);
        this.mViewPager = (ViewPager) this.findViewById(R.id.dressin_view_pager);
        this.mPagerAdapter = new WeByWeatherFragmentStatePagerAdapter(getSupportFragmentManager());
        final ActionBar actionBar = this.buildActionBarTabs();
        this.mViewPager.setAdapter(this.mPagerAdapter);
        this.mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected (final int position) {
                actionBar.setSelectedNavigationItem(position);
            }
        });
    }

    @Override
    protected void onResume () {
        super.onResume();
        this.mPagerAdapter.notifyDataSetChanged();
    }

    /**
     * Builds the ActionBar tabs
     *
     * @return {@link ActionBar} object with added tabs
     */
    private ActionBar buildActionBarTabs () {
        final ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayOptions(0);
        // Specify that a dropdown list should be displayed in the action bar.
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        // create new Statistics tab
        this.addTab(actionBar, R.string.title_me_tab);
        // create new Assignments tab
        this.addTab(actionBar, R.string.title_friends_tab);
        return actionBar;
    }

    /**
     * Adds tab to action bar
     *
     * @param actionBar - {@link ActionBar}
     * @param title     - tab's title
     */
    private void addTab (final ActionBar actionBar, final int title) {
        final ActionBar.Tab statisticsTab = actionBar.newTab().setText(this.getString(title)).setTabListener(this.tabListener);
        actionBar.addTab(statisticsTab);
    }

    /**
     * Gets the current registration id for application on GCM service.
     * <p/>
     * If result is empty, the registration has failed.
     *
     * @return registration id, or empty string if the registration is not
     * complete.
     */
    private String getRegistrationId (Context context) {
        final SharedPreferences prefs = getGCMPreferences(context);
        String registrationId = prefs.getString(Constants.PROPERTY_REG_ID, "");
        if (registrationId.length() == 0) {
            Log.v(TAG, "Registration not found.");
            return "";
        }
        // check if app was updated; if so, it must clear registration id to
        // avoid a race condition if GCM sends a message
        int registeredVersion = prefs.getInt(Constants.PROPERTY_APP_VERSION, Integer.MIN_VALUE);
        int currentVersion = getAppVersion(context);
        if (registeredVersion != currentVersion || isRegistrationExpired()) {
            Log.v(TAG, "App version changed or registration expired.");
            return "";
        }
        return registrationId;
    }

    /**
     * @return Application's {@code SharedPreferences}.
     */
    private SharedPreferences getGCMPreferences (Context context) {
        return getSharedPreferences(WeByWeatherActivity.class.getSimpleName(),
                Context.MODE_PRIVATE);
    }

    /**
     * @return Application's version code from the {@code PackageManager}.
     */
    private static int getAppVersion (Context context) {
        try {
            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            return packageInfo.versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            // should never happen
            throw new RuntimeException("Could not get package name: " + e);
        }
    }

    /**
     * Checks if the registration has expired.
     * <p/>
     * <p>To avoid the scenario where the device sends the registration to the
     * server but the server loses it, the app developer may choose to re-register
     * after REGISTRATION_EXPIRY_TIME_MS.
     *
     * @return true if the registration has expired.
     */
    private boolean isRegistrationExpired () {
        final SharedPreferences prefs = getGCMPreferences(this.mContext);
        // checks if the information is not stale
        long expirationTime =
                prefs.getLong(Constants.PROPERTY_ON_SERVER_EXPIRATION_TIME, -1);
        return System.currentTimeMillis() > expirationTime;
    }

    /**
     * Registers the application with GCM servers asynchronously.
     * <p/>
     * Stores the registration id, app versionCode, and expiration time in the
     * application's shared preferences.
     */
    private void registerBackground () {
        new AsyncTask() {
            @Override
            protected Object doInBackground (Object[] objects) {
                String msg = "";
                try {
                    if (mGcm == null) {
                        mGcm = GoogleCloudMessaging.getInstance(mContext);
                    }
                    mRegId = mGcm.register(Constants.SENDER_ID);
                    msg = "Device registered, registration id=" + mRegId;

                    // You should send the registration ID to your server over HTTP,
                    // so it can use GCM/HTTP or CCS to send messages to your app.

                    // For this demo: we don't need to send it because the device
                    // will send upstream messages to a server that echo back the message
                    // using the 'from' address in the message.

                    // Save the regid - no need to register again.
                    setRegistrationId(mContext, mRegId);
                } catch (IOException ex) {
                    msg = "Error :" + ex.getMessage();
                }
                return msg;
            }

            @Override
            protected void onPostExecute (Object o) {
                super.onPostExecute(o);
                Log.i(TAG, o.toString());
            }
        }.execute();
    }

    /**
     * Stores the registration id, app versionCode, and expiration time in the
     * application's {@code SharedPreferences}.
     *
     * @param context application's context.
     * @param regId   registration id
     */
    private void setRegistrationId (Context context, String regId) {
        final SharedPreferences prefs = getGCMPreferences(context);
        int appVersion = getAppVersion(context);
        Log.v(TAG, "Saving regId on app version " + appVersion);
        SharedPreferences.Editor editor = prefs.edit();
        editor.putString(Constants.PROPERTY_REG_ID, regId);
        editor.putInt(Constants.PROPERTY_APP_VERSION, appVersion);
        long expirationTime = System.currentTimeMillis() + Constants.REGISTRATION_EXPIRY_TIME_MS;

        Log.v(TAG, "Setting registration expiry time to " +
                new Timestamp(expirationTime));
        editor.putLong(Constants.PROPERTY_ON_SERVER_EXPIRATION_TIME, expirationTime);
        editor.commit();
    }

}
